package com.sts.common.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.sts.jdbc.model.JdbcConnectionInfo;
import org.stone.beecp.BeeDataSource;
import org.stone.beecp.BeeDataSourceConfig;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class JdbcConnectionUtil {

    private static final Map<String, DataSource> DATA_SOURCE_MAP = new ConcurrentHashMap<>();
    private static final ReentrantLock LOCK = new ReentrantLock();

    public static Connection getConnection(JdbcConnectionInfo jdbcConnectionInfo) {
        try {
            return getDataSource(jdbcConnectionInfo).getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static BeeDataSourceConfig buildBeeDataSourceConfig(JdbcConnectionInfo jdbcConnectionInfo) {
        BeeDataSourceConfig beeDataSourceConfig = new BeeDataSourceConfig();
        beeDataSourceConfig.setDriverClassName(jdbcConnectionInfo.getDriverClassName());
        beeDataSourceConfig.setUrl(jdbcConnectionInfo.getUrl());
        beeDataSourceConfig.setUsername(jdbcConnectionInfo.getUsername());
        beeDataSourceConfig.setPassword(jdbcConnectionInfo.getPassword());
        beeDataSourceConfig.setInitialSize(jdbcConnectionInfo.getInitialSize());
        beeDataSourceConfig.setMaxActive(jdbcConnectionInfo.getMaxActive());
        beeDataSourceConfig.setEnableThreadLocal(false);

        return beeDataSourceConfig;
    }

    public static DataSource getDataSource(JdbcConnectionInfo jdbcConnectionInfo) {
        DataSource beeDataSource;
        String connectionName = jdbcConnectionInfo.getName();
        if (!DATA_SOURCE_MAP.containsKey(connectionName)) {
            LOCK.lock();
            try {
                if (!DATA_SOURCE_MAP.containsKey(connectionName)) {
                    beeDataSource = new BeeDataSource(buildBeeDataSourceConfig(jdbcConnectionInfo));
                    DATA_SOURCE_MAP.put(connectionName, beeDataSource);
                } else {
                    beeDataSource = DATA_SOURCE_MAP.get(connectionName);
                }
            } finally {
                LOCK.unlock();
            }
        } else {
            beeDataSource = DATA_SOURCE_MAP.get(connectionName);
        }
        return beeDataSource;
    }

    public static void closeAll() {
        if (CollectionUtil.isNotEmpty(DATA_SOURCE_MAP)) {
            try {
                for (Map.Entry<String, DataSource> entry : DATA_SOURCE_MAP.entrySet()) {
                    BeeDataSource beeDataSource = (BeeDataSource) entry.getValue();
                    beeDataSource.clear(true);
                    beeDataSource.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
            DATA_SOURCE_MAP.clear();
        }
    }

}
